package ltg.ibutton.core;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Observable;

import ltg.ibutton.core.wrappers.FactoryWrapper;
import ltg.ibutton.core.wrappers.Wrapper;

public class Reader extends Observable {
	private String id;
	private ArrayList<Button> attachedButtons = new ArrayList<Button>();
	private boolean keeprunning = false;
	private ReaderUpdater rupdater = null;
	private int sleepTime = 1;
	
	public Reader(String id) {
		this.id = id;
		this.updateButtonList();
	}
	
	public String getId() {
		return id;
	}
	
	public ArrayList<Button> getAttachedButtons() {
		return this.attachedButtons;
	}
	
	public void addButton(Button i) {
		if(i != null)
			this.attachedButtons.add(i);
	}
	
	public void removeButton(Button i) {
		if(i != null)
			this.attachedButtons.remove(i);
	}
	
	public String toString() {
		String str = "Reader: " + this.getId() + "\n";
		if(!this.attachedButtons.isEmpty())
			for(Iterator<Button> i = this.attachedButtons.iterator(); i.hasNext();) {
				Button b = (Button) i.next();
				str += "\t|---- " + b.toString();
			}
		return str;
	}
	
	public ArrayList<String> updateButtonList() {
		Wrapper wrp = FactoryWrapper.getWrapper();
		boolean changed = false;
		ArrayList<Button> tmp = new ArrayList<Button>();
		ArrayList<String> ret = null;
		
		for(Iterator<String> j = wrp.getButtonsFromReader(this.getId()).iterator(); j.hasNext();) {//check for new additions
			Button currentbid = new Button((String) j.next());
			tmp.add(currentbid);
			if(!this.attachedButtons.contains(currentbid))
				changed = true;
		}
		for(Iterator<Button> j = this.attachedButtons.iterator(); j.hasNext();) {//check for removal
			Button currentbid = ((Button) j.next());
			if(!tmp.contains(currentbid)) {
				changed = true;
			}
		}
		
		if(changed) {
			this.attachedButtons.clear();
			this.attachedButtons = tmp;
			ret = new ArrayList<String>();
			for(Iterator<Button> j = this.attachedButtons.iterator(); j.hasNext();) {
				ret.add(((Button) j.next()).getId());
			}
		}
		return ret;
	}
	
	public synchronized void start() {
		if (rupdater==null || !rupdater.isAlive()) {
            this.rupdater = new ReaderUpdater();
            keeprunning=true;
            rupdater.start();
		}
	}

	public synchronized void stop() {
		 if (rupdater!=null && rupdater.isAlive()) {
             keeprunning = false;
             rupdater = null;
		 }
	}
	
	public int getSleepTime() {
		return sleepTime;
	}

	public void setSleepTime(int sleepTime) {
		this.sleepTime = sleepTime;
	}
	
	private final class ReaderUpdater extends Thread {
		/**
		 * Builds a thread with a certain name.
		 * @param thread name
		 */
		public ReaderUpdater() {
			super();
		}

		/**
		 * This performs the main update cycle. 
		 * The cycle is: update, notify the observers and
		 * then finally sleep for a while.
		 */
		public void run() {
			while(keeprunning) {
				ArrayList<String> newID = updateButtonList();
				if(newID != null) { //null no change
					setChanged();
					notifyObservers(newID);
				}
				//System.err.println(Reader.this.toString());
				//System.err.println("*************************************************");
				try {
					Thread.sleep(sleepTime*1000);
				} catch (InterruptedException e) {
					e.printStackTrace();
					break;
				}
			}
		}
	}
	
}
